// C source file with the function definitions to handle generic arrays

// check_array()
// function to check the paramaters of a raw array
bool check_array(byte * arr, umax asize, umax var_size)
{
  return (check_byte_array(arr, asize) && var_size != 0);
}

// print_arr_elems() function
// function to print the elements of a raw array. It needs the array size, the
// size of an individual element and also a function that can "print" the element
umax print_arr_elems(byte * arr, umax asize, umax var_size, umax (* print_elem) (byte *, umax))
{
  // check function parameters
  if (check_array(arr, asize, var_size) == false || print_elem == NULL)
    return 0;
  
  // print the array elements 
  for (umax i = 0; i < asize; i++) {
    arr += print_elem(arr, var_size);
    putchar(' ');
  }
  
  // end the line and return the number of bytes read
  putchar('\n');
  return asize * var_size;
}

// reverse_arr() function
// function to reverse the order of the variables of an array
// it is a raw byte mevement basically, considering variable size
umax reverse_arr(byte * arr, umax asize, umax var_size)
{
  // check function parameters
  if (check_array(arr, asize, var_size) == false)
    return false;
  
  // calculate the middle position (truncated)
  umax mid_pos = (asize / 2);
  // create temp array to hold the array variable's bytes when doing the data movement
  mem_space * elem_tmp = create_mem_space(var_size);
  // cast the array pointer conveniently (pointer to arrays of size var_size that contain bytes)
  byte (* ptr)[var_size] = (void *) arr;
  // swap array elements positions
  for (umax i = 0; i < mid_pos; i++) {
    // swap element i with element arr_size - i - 1
    cp_mem_bytes(ptr[i], var_size, elem_tmp -> ptr);
    cp_mem_bytes(ptr[asize - i - 1], var_size, ptr[i]);
    cp_mem_bytes(elem_tmp -> ptr, var_size, ptr[asize - i - 1]);
  }
  
  // free memory used
  free_mem_space(elem_tmp);
  return true;
}

// find_arr_elem() function
// function to find for an element of in an array.
// it will return the first occurrence of the element. Needs a function to make the comparison.
byte * find_arr_elem(byte * elem, umax esize, byte * arr, umax asize, bool (* comp_elems) (byte *, byte *))
{
  // check function parameters
  if (check_byte_array(elem, esize) == false || check_byte_array(arr, asize) == false || comp_elems == NULL)
    goto err;
  
  // search in array for said element
  for (umax i = 0; i < asize; i++, arr += esize)   
    if (comp_elems(elem, arr))
      return arr;
  
  err: // error/element not found
  return NULL;  
}

// sort_arr() function
// function to sort the contents of an array
// this function will order elements from "lower" to "larger"
umax sort_arr(byte * arr, umax asize, umax var_size, bool (* comp_elems) (byte *, byte *))
{
  // check function parameters
  if (check_array(arr, asize, var_size) == false || comp_elems == NULL)
    return false;
  
  // create temporal array to hold the array data to be moved
  mem_space * elem_tmp = create_mem_space(var_size);
  // cast the array pointer conveniently (pointer to arrays of size var_size that contain bytes)
  byte (* ptr)[var_size] = (void *) arr;
  // compare each array elements  
  for (umax i = 0; i < asize; i++)
    for (umax j = i + 1; j < asize; j++)
      // swap element i and element j positions
      if (comp_elems(ptr[i], ptr[j])) {
        cp_mem_bytes(ptr[j], var_size, elem_tmp -> ptr);
        cp_mem_bytes(ptr[i], var_size, ptr[j]);
        cp_mem_bytes(elem_tmp -> ptr, var_size, ptr[i]);
      }
  
  // free memory used and return the byte size of the array
  free_mem_space(elem_tmp);
  return asize * var_size;
}
